<?php
/**
 * Created by PhpStorm.
 * User: 7howe
 * DateTime: 2019/11/22 20:33
 */

namespace app\order\model;

use think\Model as ThinkModel;
use app\common\model\Order as OrderModel;
use think\Db;

class OrderGoodsExpress extends ThinkModel
{
    
    /**
     * 调用API-快递鸟    
     */
    private static function getKuaidiNiao($express_no,$company_sn,$order_sn,$mobile = null){        
        $query = addons_action('ExpressBird/Api/getOrderTracesByJson', [$order_sn, $company_sn, $express_no]); 
        return $query;
    }
    
     /**
     * 调用API-阿里云市场    
     */
    private static function getAliYun($express_no,$company_sn,$order_sn,$mobile = null){      
        \com\Kuaidi::setAppcode(module_config('order.kuaidi_appcode'));         
        if(in_array($company_sn,['SFGJ',"NSF","SF"])){
            $mobile = $mobile ?: OrderInfo::where("order_sn",$order_sn)->value("receiver_mobile");
            $query = \com\Kuaidi::query($express_no,$company_sn,$mobile);
        }else{
            $query = \com\Kuaidi::query($express_no,$company_sn);
        } 
        return $query;
    }

    //获取物流信息
    //定制接口内容
    public static function getQuery($express_no,$company_sn,$order_sn,$mobile = null){
      
        $key = $company_sn . $express_no;
        $no = $company_sn . ":". $express_no;
        $query = \think\Db::name("order_goods_express_query")->where("express_no",$no)->value("query");
        if($query){
            $query = json_decode($query,true);    
        } else{
            $query =  cache("express_query:" .$key);
        }              
        if($query){
            $query["Traces"] = $query["Traces"]  ? array_reverse($query["Traces"]) : [];
            return $query;
        }
        try{           
            //默认使用阿里云接口
            $query =  self::getKuaidiNiao($express_no,$company_sn,$order_sn,$mobile);  
            // $query =  self::getAliYun($express_no,$company_sn,$order_sn,$mobile);      
        }catch(\Exception $e){
            return [
                "LogisticCode"=> $express_no,
                "ShipperCode"=> $company_sn,
                "Traces"=> [],
                "State"=> "0",
                "Reason"=> "暂无轨迹信息",
                "Success"=> false,
             ];
        }                 
         //缓存十分钟
        cache("express_query:" .$key,$query,10);
       
        if($query["State"] >= 3){
            cache("express_query:" . $key,null);        
            \think\Db::name("order_goods_express_query")->insert([
                "express_no"=>$no,
                "query"=>json_encode($query,JSON_UNESCAPED_UNICODE)
            ]);
        }
        // $query["Traces"] = $query["Traces"]  ? array_reverse($query["Traces"]) : [];
        return $query;
    }
    
    /**
     * 生成发货单
     * @author 晓风<215628355@qq.com>
     * @param array $request
     * @return boolean
     * @throws \Exception
     */
    public static function createExpress(array $request ){
        $validate = \think\facade\App::instance()->validate(\app\order\validate\Express::class);
        $check = $validate->scene("create")->check($request);
        if(!$check){
            throw new \Exception($validate->getError());
        }
          
        $map[] =  ["order_sn","=",$request["order_sn"]];
        $map[] =  ["status","=",1];      
        $order = OrderModel::where($map)->where("order_type","in",[3])->find();
        if(!$order){
            throw new \Exception('无法操作此订单' . $request["order_sn"]);
        }   
        $express_company = \app\goods\model\ExpressCompany::get($request['express_company']);
        if(!$express_company){
            throw new \Exception("快递公司选择错误");
        }
        $sender = Db::name('goods_express_sender')->get($request['sender_id']);
         if(!$sender){
            throw new \Exception("发件地址选择不正确");
        }            
        
        //$goods = OrderGoods::where('order_sn', $request["order_sn"])->field('goods_id,sku_id')->select();
        //$goods_array = [];
       // foreach ($goods as $item) {
        //    $goods_array[] = $item['goods_id'] . '_' . $item['sku_id'];
       // }
       
        $param['order_sn'] = $request['order_sn'];
        //$param['order_goods_id_array'] = implode(',', $goods_array); //该字段无用处暂时屏蔽
        $param['express_serial_number'] = date("Ymd", time()) . rand(100000, 999999);
        $param['express_name'] = '';
        $param['shipping_type'] = 1;//
        $param['express_company_id'] = $express_company['aid'];
        $param['express_company'] = $express_company['name'];
        $param['express_no'] = $request["express_no"];
        $param['uid'] = defined('UID') ? UID : 0;
        $param['memo'] = $request["memo"] ?? "";
        $param['shipping_time'] = time();  
        $param['is_del'] = 0;//
        $check = OrderGoodsExpress::where(["order_sn" => $request["order_sn"]])->count();
        if($check){
            $res = self::where(["order_sn" => $request["order_sn"]])->update($param);
        }  else{
            $res = self::create($param);
        }        
        if (!$res) {
            throw new \Exception(lang('生成发货单失败'));
        }
        $res = OrderModel::where('order_sn',  $request['order_sn'])->update([
            'sender_id' => $sender['id'],
            'update_time' => time()
        ]);
        if (!$res) {
            throw new \Exception(lang('生成发货单失败（发货人失败）'));
        }
        OrderAction::addLog($request["order_sn"] , lang('管理员生成发货单') , 1 );   
      
        /**
         * 因生成发货单过去频繁，故暂时取消该消息发送，如有需要可以打开注释
        $thumb = OrderGoods::where("order_sn",$request["order_sn"])->value("goods_thumb");  
        \app\operation\model\SystemMessage::create([
            "to_user_id"=> $order['user_id'], 
            "title"=>'您的订单已出库',
            "order_sn"=>$order['order_sn'],
            "content"=> "您的商品订单：" . $order["order_sn"] . ", 已经出库，\n即将由快递公司：". $express_company["name"] . "发出。",        
            "msg_type"=>2,    
            "thumb"=>$thumb ?:0,
            "custom"=>json_encode(['type'=>'order','id'=> $order["order_sn"]]),        
        ]);     
        **/
        return true;
    }

    /**
     * 批量导入发货
     * php迷途小书童 2022/5/12 9:53 上午
     * @param $param
     * @return array
     */
    public function importExpressExcel($param)
    {
        $map = [];
        $map[] = ["order_sn", "=", $param["order_sn"]];
        $map[] = ["status", "=", 1];
        $order = OrderModel::where($map)->where("order_type", "in", [3])->find();
        if (!$order) {
            throw new \Exception('无法操作此订单');
        }
        $refund = OrderRefund::where("status", "in", [0, 1, 2])->where("order_sn", $order["order_sn"])->count();
        if ($refund > 0) {
            throw new \Exception('该订单有' . $refund . "笔进行中的退款，请先处理退款");
        }

        $express_company = \app\goods\model\ExpressCompany::get($param['express_company_id']);
        if (!$express_company) {
            throw new \Exception("快递公司选择错误");
        }
        $update = [];
        $update['order_sn'] = $order['order_sn'];
        $update['order_goods_id_array'] = $param['og_id'];
        $update['express_serial_number'] = date("Ymd", time()) . rand(100000, 999999);
        $update['express_name'] = '';
        $update['shipping_type'] = 1;//
        $update['express_company_id'] = $express_company['aid'];
        $update['express_company'] = $express_company['name'];
        $update['express_no'] = $param["express_no"];
        $update['uid'] = defined('UID') ? UID : 0;
        $update['memo'] = $param["memo"] ?? "";
        $update['shipping_time'] = time();
        $update['express_status'] = 1;
        $info = self::where(["order_sn" => $param["order_sn"]])
            ->where('order_goods_id_array', $param['og_id'])
            ->field("id,express_no")->find();
        if ($info) {
            $res = self::where("id", $info["id"])->update($update);
        } else {
            $res = self::create($update);
        }
        if (!$res) {
            throw new \Exception("发货失败");
        }
        OrderGoods::where('id', $param['og_id'])->update(['shipping_status' => 1, 'express_no' => $param['express_no']]);
        //考虑到退单的部分，这里必须做两个查询处理
        OrderGoods::where('id', $param['og_id'])->where("order_status", 1)->update(['order_status' => 2]);
        // 修改订单状态
        OrderModel::where('order_sn', $order['order_sn'])->update(['status' => 2]);
        //OrderInfo::where('order_sn', $order['order_sn'])->update(['shipping_company_id' => $express_company["aid"], 'consign_time' => time()]);
        //删除消息提醒
        Db::name('order_remind')->where('order_sn', $order['order_sn'])->delete();

        $action = '平台发货';
        OrderAction::addLog($order["order_sn"], $action, 2, 0, $param['memo']);
        $thumb = OrderGoods::where('id', $param['og_id'])->value("goods_thumb");
        \app\operation\model\SystemMessage::create([
            "to_user_id" => $order['user_id'],
            "title" => '您的订单已发货',
            "order_sn" => $order['order_sn'],
            "content" => "您的商品订单：" . $order["order_sn"] . ", 已经发货，\n快递公司：" . $express_company['name'] . "，运单号：" . $param["express_no"],
            "msg_type" => 2,
            "thumb" => $thumb ?: 0,
            "custom" => json_encode(['type' => 'order', 'id' => $order["order_sn"]])
        ]);
        return $update;
    }
    
    /**
     * 直接发货
     * 三端操作，合并到模型里
     * @author 晓风
     * @throws \Exception
     */
    public static function addExpress(array $request ){     
        
        $validate = \think\facade\App::instance()->validate(\app\order\validate\Express::class);
        $check = $validate->check($request);
        if(!$check){
            throw new \Exception($validate->getError());
        }
         
        $map[] =  ["order_sn","=",$request["order_sn"]];
        $map[] =  ["status","=",1];      
        $order = OrderModel::where($map)->where("order_type","in",[3])->find();
        if(!$order){
            throw new \Exception('无法操作此订单');
        }   
        $refund = OrderRefund::where("status","in",[0,1,2])->where("order_sn",$order["order_sn"])->count();
        if($refund > 0){
            throw new \Exception('该订单有'. $refund . "笔进行中的退款，请先处理退款");
        }
        
        $express_company = \app\goods\model\ExpressCompany::get($request['express_company']);
        if(!$express_company){
            throw new \Exception("快递公司选择错误");
        }
        $sender = Db::name('goods_express_sender')->get($request['sender_id']);
         if(!$sender){
            throw new \Exception("发件地址选择不正确");
        }
        //如果需要使用快递鸟发货，请去掉验证器之中的express_no必填验证，并在控制器中添加是否生成快递鸟面单的选择，实际上用处不大
        //$request["express_no"] = self::createKuaidiNiaoOrder( $order['order_sn'],$express_company,$sender);
        
        //order_goods_id_array 这个不知道干嘛，也没有发现其他用途，暂时屏蔽
        //$goods = OrderGoods::where('order_sn', $order['order_sn'])->field('goods_id,sku_id')->select();
        //$goods_array = [];
        //foreach ($goods as $item) {
        //    $goods_array[] = $item['goods_id'] . '_' . $item['sku_id'];
        //}
               
        $param['order_sn'] = $order['order_sn'];
        //$param['order_goods_id_array'] = implode(',', $goods_array); //该字段无用处暂时屏蔽
        $param['express_serial_number'] = date("Ymd", time()) . rand(100000, 999999);
        $param['express_name'] = '';
        $param['shipping_type'] = 1;//
        $param['express_company_id'] = $express_company['aid'];
        $param['express_company'] = $express_company['name'];
        $param['express_no'] = $request["express_no"];
        $param['uid'] = defined('UID') ? UID : 0;
        $param['memo'] = $request["memo"] ?? "";
        $param['shipping_time'] = time();  
        $param['express_status'] = 1;
        $info = self::where(["order_sn" => $request["order_sn"]])->field("id,express_no")->find();
        if($info){
            $res = self::where("id",$info["id"])->update($param);
        }else{
            $res = self::create($param);
        }   
        if(!$res){
            throw new \Exception("发货失败");
        }  
        OrderGoods::where('order_sn', $order['order_sn'])->update(['shipping_status' => 1, 'express_no' => $param['express_no'] ]);
        //考虑到退单的部分，这里必须做两个查询处理
        OrderGoods::where('order_sn', $order['order_sn'])->where("order_status",1)->update(['order_status' => 2]);  
        // 修改订单状态
        OrderModel::where('order_sn', $order['order_sn'])->update(['status' => 2, "sender_id"=>$request['sender_id']]);   
        //OrderInfo::where('order_sn', $order['order_sn'])->update(['shipping_company_id' => $express_company["aid"], 'consign_time' => time()]);   
        //删除消息提醒
        Db::name('order_remind')->where('order_sn', $order['order_sn'])->delete();           
        
        $action = '平台发货';
        OrderAction::addLog($order["order_sn"] , $action , 2 , 0 ,  $param['memo'] );   
        $thumb = OrderGoods::where("order_sn",$order["order_sn"])->value("goods_thumb");
        \app\operation\model\SystemMessage::create([
            "to_user_id"=> $order['user_id'], 
            "title"=>'您的订单已发货',
            "order_sn"=>$order['order_sn'],
            "content"=> "您的商品订单：" . $order["order_sn"] . ", 已经发货，\n快递公司：".$express_company['name'] . "，运单号：". $request["express_no"],        
            "msg_type"=>2,    
            "thumb"=>$thumb ?:0,
            "custom"=>json_encode(['type'=>'order','id'=> $order["order_sn"]])
        ]);       
        return $param;
    }
    /**
     * 发货单中的单件发货
     * 暂不考虑性能问题
     * @author 晓风<215628355@qq.com>
     * @param int $id
     * @param string $express_no
     * @param string $remark
     * @throws \Exception
     */
    public static function setExpress(int $id,string $express_no,string $remark = ""){
        $save_data = [
            "express_no" => $express_no,
            "memo" => $remark,
            "shipping_time" => time(),
            "express_status" => 1
        ];
        $validate = \think\facade\App::instance()->validate(\app\order\validate\Express::class);
        $check = $validate->scene('edit')->check($save_data);
        if(!$check){
            throw new \Exception($validate->getError());
        }        
        $info = self::get($id);
        if(!$info){
            throw new \Exception("未找到发货单" . $id);
        }
        //此处请根据需要，进行处理，一般会存在合并发货的情况
        //$check = self::where('express_no' , $express_no)->find();
        //if ($check) {
        //   throw new \Exception(lang('发货单号已存在，请核实' . $express_no));
        //}
        $map[] =  ["order_sn","=",$info["order_sn"]];
        $map[] =  ["status","=",1];      
        $order = OrderModel::where($map)->where("order_type","in",[3])->find();
        if(!$order){
            throw new \Exception('无法操作此订单' . $info["order_sn"]);
        }   
        $refund = OrderRefund::where("status","in",[0,1,2])->where("order_sn",$order["order_sn"])->count();
        if($refund > 0){
            throw new \Exception('该订单有'. $refund . "笔进行中的退款，请先处理退款" . $info["order_sn"]);
        }    
      
        $res = self::where("id", $info['id'])->update($save_data);
        if (!$res) {
             throw new \Exception(lang('发货失败' .  $info['id']));
        }        
        OrderGoods::where('order_sn', $order['order_sn'])->update(['shipping_status' => 1, 'express_no' => $express_no ]);
        //考虑到退单的部分，这里必须做两个查询处理
        OrderGoods::where('order_sn', $order['order_sn'])->where("order_status",1)->update(['order_status' => 2]);  
        // 修改订单状态
        OrderModel::where('order_sn', $order['order_sn'])->update(['status' => 2 ]);   
        //OrderInfo::where('order_sn', $order['order_sn'])->update(['shipping_company_id' => $express_company["aid"], 'consign_time' => time()]);   
        //删除消息提醒
        Db::name('order_remind')->where('order_sn', $order['order_sn'])->delete();           
        
        $action = '平台发货';
        OrderAction::addLog($order["order_sn"] , $action , 2 , 0 , $remark );   
        $thumb = OrderGoods::where("order_sn",$order["order_sn"])->value("goods_thumb");
        $name = (string)\app\order\model\ExpressCompany::where("aid",$info['express_company_id'])->value("name");
        \app\operation\model\SystemMessage::create([
            "to_user_id"=> $order['user_id'], 
            "title"=>'您的订单已发货',
            "order_sn"=>$order['order_sn'],
            "content"=> "您的商品订单：" . $order["order_sn"] . ", 已经发货，\n快递公司：". $name . "，运单号：". $express_no,        
            "msg_type"=>2,    
            "thumb"=>$thumb ?:0,
            "custom"=>json_encode(['type'=>'order','id'=> $order["order_sn"]])
        ]);     
        $info["express_no"] = $express_no;
        return $info;
    }

    
    /**
     * 发货单中的单件取消发货
     * 暂不考虑性能问题
     * @author 晓风<215628355@qq.com>
     * @param int $id
     * @param string $express_no
     * @param string $remark
     * @throws \Exception
     */
    public static function canalExpress(int $id, string $remark = ""){
        
        $info = self::get($id);
        if(!$info){
            throw new \Exception("未找到发货单");
        }       
        $map[] =  ["order_sn","=",$info["order_sn"]];
        $map[] =  ["status","=",2];      
        $order = OrderModel::where($map)->where("order_type","in",[3])->find();
        if(!$order){
            throw new \Exception('无法操作此订单');
        }   
        $save_data = [
            "express_status"=>0,
            "express_no"=>"",
            "memo"=>$remark
        ];      
        $res = self::where("id", $info['id'])->update($save_data);
        if (!$res) {
             throw new \Exception(lang('取消失败'));
        }        
        OrderGoods::where('order_sn', $order['order_sn'])->update(['shipping_status' => 0, 'express_no' => "" ]);
        //考虑到退单的部分，这里必须做两个查询处理
        OrderGoods::where('order_sn', $order['order_sn'])->where("order_status",2)->update(['order_status' => 1]);  
        // 修改订单状态
        OrderModel::where('order_sn', $order['order_sn'])->update(['status' => 1 ]);   
        //OrderInfo::where('order_sn', $order['order_sn'])->update(['shipping_company_id' => $express_company["aid"], 'consign_time' => time()]);   
         
        $action = '平台取消发货';
        OrderAction::addLog($order["order_sn"] , $action , 1, 0 , $remark );   
        $thumb = OrderGoods::where("order_sn",$order["order_sn"])->value("goods_thumb");       
        \app\operation\model\SystemMessage::create([
            "to_user_id"=> $order['user_id'], 
            "title"=>'您的订单已取消发货',
            "order_sn"=>$order['order_sn'],
            "content"=> "您的商品订单：" . $order["order_sn"] . ", 已取消发货",        
            "msg_type"=>2,    
            "thumb"=>$thumb ?:0,
            "custom"=>json_encode(['type'=>'order','id'=> $order["order_sn"]])
        ]);     
        $info["express_no"] = "";
        return $info;
    }


    /**
     * 生成快递鸟面单号
     * @author 晓风<215628355@qq.com>
     * @param string $order_sn 订单号
     * @param array $express_company 快递公司
     * @param array $sender 发件人
     * @return type
     */
    public static function createKuaidiNiaoOrder($order_sn,$express_company,$sender){
        $order_info = OrderInfo::where('order_sn', $order_sn)->find();
        $eorder['ShipperCode'] = $express_company['express_no'];
        $eorder['OrderCode'] = $order_sn;
        $eorder["PayType"] = $sender['pay_type'];//邮费支付方式:1现付,2到付,3月结,4第三方支付
        $_sender["Name"] = $sender['name'];  //发件人姓名
        $_sender["Mobile"] = $sender['phone'];  //发件人电话
        $_sender["ProvinceName"] = $sender['province'];  //发件人所在省
        $_sender["CityName"] = $sender['city'];  //发件人所在市
        $_sender["ExpAreaName"] = $sender['area'];  //发件人所在区
        $_sender["Address"] = $sender['address'];  //发件人地址
        $receiver["Name"] = $order_info['receiver_name'];   //收件人
        $receiver["Mobile"] = $order_info['receiver_mobile']; //收件人电话
        $receiver["ProvinceName"] = $order_info['province']; //收件人省
        $receiver["CityName"] = $order_info['city']; //收件人市
        $receiver["ExpAreaName"] = $order_info['district']; //收件人区
        $receiver["Address"] = $order_info['receiver_address']; //收件人地址          
        $result = addons_action('Express/Api/submitOOrder', [$eorder, $_sender, $receiver]);
        $result = json_decode($result, true);               
        return  $result['order']['LogisticCode'];
    }
}
